

#include<vector>
#include<iostream>
#include<string.h>
#include<string>
#include<cassert>

class Buffer
{
private:
    std::vector<char> _buffer;
    uint64_t _read_idx;
    uint64_t _write_idx;
public:
    Buffer()
    :_read_idx(0),_write_idx(0),_buffer(1024)
    {

    }
    ~Buffer()
    {

    }
    char * Begin() { return &(*_buffer.begin()); }
    //获取读地址
    char * ReadPosition() { return Begin() + _read_idx; }
    //获取写地址
    char * WritePosition() { return Begin() + _write_idx; }
    //获取前沿空闲大小
    uint64_t HeadIdleSize() { return _read_idx; }
    //获取后沿空闲大小
    uint64_t TailIdleSize() { return _buffer.size() - _write_idx; }
    //获取可读空间大小
    uint64_t ReadAbleSize(){ return _write_idx - _read_idx; }
    //将读偏移向后偏移
    void MoveReadOffSet(uint64_t len){ assert(len <= ReadAbleSize()); _read_idx += len;}
    //将写偏移向后偏移
    void MoveWriteOffSet(uint64_t len){ assert( len <= TailIdleSize()); _write_idx += len;}
    //确保写入空间足够(若剩余空间大于len，就将数据移动到前面，若是剩余空间小于len，就扩容)
    void EnsureWriteSpace(uint64_t len)
    {
        //末尾的空间足够
        if(len <= TailIdleSize())
        {
            return;
        }
        //若是剩余的空间足够，就将数据向前偏移
        if(len <= TailIdleSize() + HeadIdleSize())
        {
            uint64_t rsz = ReadAbleSize();
            //需要保存的数据就是从读偏移量的位置开始，长度为可读长度，然后复制到_buffer的begin中
            std::copy(ReadPosition(),ReadPosition() + rsz,Begin());
            _read_idx = 0;
            _write_idx += rsz;
        }
        //若是剩余的空间都不够，就需要扩容
        else{
            _buffer.resize(_write_idx + len);
        }
    }
    //写入数据(将inbuffer中的数据保存到Buffer中，长度为len)
    void Write(const void * inbuffer,uint64_t len)
    {
        EnsureWriteSpace(len);
        const char * d = (const char*)inbuffer;
        std::copy(d,d+len,WritePosition());
    }

    void WriteAndPush(const void * inbuffer,uint64_t len)
    {
        Write(inbuffer,len);
        MoveWriteOffSet(len);
    }

    void WriteAsString(std::string& inbuffer)
    {
        Write(inbuffer.c_str(),inbuffer.size());
    }
    void WriteAsStringAndPush(std::string& inbuffer)
    {
        Write(inbuffer.c_str(),inbuffer.size());
        MoveWriteOffSet(inbuffer.size());
    }

    void WriteAsBuffer(Buffer& inbuffer)
    {
        Write(inbuffer.ReadPosition(),inbuffer.ReadAbleSize());
    }
    
    void WriteAsBufferAndPush(Buffer& inbuffer)
    {
        WriteAsBuffer(inbuffer);
        MoveWriteOffSet(inbuffer.ReadAbleSize());
    }

    //读取数据(将Buffer中长len的数据给到outbuffer中去)
    void Read(void* outbuffer,uint64_t len)
    {
        assert(len <= ReadAbleSize());
        std::copy(ReadPosition(),ReadPosition() + len,(char*)outbuffer);
    }
    void ReadAndPush(void* outbuffer,uint64_t len)
    {
        Read(outbuffer,len);
        MoveReadOffSet(len);
    }

    std::string ReadAsString(uint64_t len)
    {
        assert(len <= ReadAbleSize());
        std::string str;
        str.resize(len);
        Read(&str[0],len);
        return str;
    }
    std::string ReadAsStringAndPop(uint64_t len)
    {
        std::string str;
        str = ReadAsString(len);
        MoveReadOffSet(len);
        return str;
    }

    char* FindCRLF()
    {
        void * res = memchr(ReadPosition(),'\n',ReadAbleSize());
        return (char*)res;
    }

    std::string GetOneLine()
    {
        char* pos = FindCRLF();
        if(pos == NULL)
        {
            return "";
        }
        std::string str;
        str = ReadAsString(pos - ReadPosition() + 1);
        return str;
    }

    std::string GetOneLineAndPop()
    {
        std::string str = GetOneLine();
        MoveReadOffSet(str.size());
        return str;
    }

    //清空数据
    void Clear()
    {
        _read_idx = 0;
        _write_idx = 0;
    }
    
};

